package com.hhdz.barrage.ui;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.view.animation.Animation;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.hhdz.barrage.R;
import com.hhdz.barrage.model.BeanItem;
import com.hhdz.barrage.service.SocketService;
import com.hhdz.barrage.utils.AnimationHelper;
import com.hhdz.barrage.utils.BarrageBean;
import com.hhdz.barrage.utils.Constant;
import com.hhdz.barrage.utils.Logcat;
import com.hhdz.barrage.utils.ScreenUtils;
import com.hhdz.barrage.work.Worker;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class MainActivity extends Activity implements Worker.DataReceivedCallback {

    private final int SHOW_BARRAGE = 0x0;

    private RelativeLayout mBarrageContainer = null;
    private BarrageBean mBarrageBean = null;
    private Worker mWorker = null;
    private final Map<String, String> mAddrToName = new HashMap<String, String>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
        mBarrageBean = new BarrageBean();
        mBarrageBean.setItems(new String[]{
                "你好", "欢迎", "你好", "欢迎",
                "你好", "欢迎", "你好", "欢迎",
                "你好", "欢迎", "你好", "欢迎",
                "你好", "欢迎", "你好", "欢迎",
                "你好", "欢迎", "你好", "欢迎",
                "中国", "安徽", "合肥", "蜀山"
        });
//        initWork();
        start();
        loadResources();
        registerReceiver(mReceiver,new IntentFilter(Constant.ACTION_POP));
    }

    @Override
    public void onDataReceived(JSONObject json) {
        try {
            String mac;
            JSONArray array = json.getJSONArray("ds");
            for (int i = 0;i<array.length();i++) {
                mac = array.getJSONObject(i).getString("da");
                Message msg = new Message();
                msg.what = SHOW_BARRAGE;
                msg.obj = mAddrToName.get(mac);
                mHandler.sendMessage(msg);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(Constant.ACTION_POP)) {
                Message msg = new Message();
                msg.what = SHOW_BARRAGE;
                msg.obj = mAddrToName.get(intent.getStringExtra(Constant.EXTRA_MAC));
                mHandler.sendMessage(msg);
            }
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
//        mWorker.terminate();
        unregisterReceiver(mReceiver);
    }

    @Override
    protected void onPause() {
        super.onPause();
        finish();
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        finish();
    }

    private void initWork() {
        mWorker = new Worker(this);
        mWorker.setDataListener(this);
        Logcat.INFO("start listening");
        mWorker.start();
    }

    private void start() {
        Intent intent = new Intent(this, SocketService.class);
        startService(intent);
    }

    private void initViews() {
        mBarrageContainer = (RelativeLayout) findViewById(R.id.barrage_container);
    }

    private void loadResources() {
        Logcat.TRACE_CALL();
        try {
            final InputStream is = getAssets().open("whitelist.json");
            final byte[] buffer = new byte[8192]; //XXX
            int len = is.read(buffer);
            Logcat.DEBUG("len: " + len);
            final JSONArray arr = new JSONArray(new String(Arrays.copyOf(buffer, len)));
            len = arr.length();
            for (int i = 0; i < len; i++) {
                final JSONObject o = arr.getJSONObject(i);
                final String addr = (String) o.keys().next();
                final String name = o.getString(addr);
                mAddrToName.put(addr, name);
            }
        } catch (Resources.NotFoundException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private Set existBeans = new HashSet<String>();

    private void showBarrage(String content, float textSize, int textColor) {

        if (hasBean(content)) {
            return;
        }
        existBeans.add(content);

        final TextView textView = new TextView(this);

        textView.setTextSize(textSize);
        textView.setText(content);
        textView.setTextColor(textColor);

        int leftMargin = mBarrageContainer.getRight() - mBarrageContainer.getLeft() - mBarrageContainer.getPaddingLeft();
        int verticalMargin = getRandomTopMargin();
        textView.setTag(new BeanItem(content,verticalMargin));

        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
        params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
        params.topMargin = verticalMargin;

        textView.setLayoutParams(params);
        Animation anim = AnimationHelper.createTranslateAnim(this, leftMargin, -ScreenUtils.getScreenWidth(this));
        anim.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                //移除该组件
                mBarrageContainer.removeView(textView);
                //移除占位
                BeanItem beanItem = (BeanItem) textView.getTag();
                existMarginValues.remove(beanItem.margin);
                existBeans.remove(beanItem.name);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        textView.startAnimation(anim);

        mBarrageContainer.addView(textView);
    }

    private boolean hasBean(String name) {
        return existBeans.contains(name);
    }

    private class CreateTanmuThread implements Runnable {
        @Override
        public void run() {
            int N = mBarrageBean.getItems().length;
            while (true) {
                int r = Math.round((float) Math.random() * (N-1));
                SystemClock.sleep(100);
                mHandler.obtainMessage(SHOW_BARRAGE, r, 0).sendToTarget();
            }
        }
    }

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == SHOW_BARRAGE) {
                // show barrage
                int index = msg.arg1;
                String content = (String)msg.obj;
                if (content == null) {
                    return;
                }
                float textSize = (float) (mBarrageBean.getMinTextSize() * (1));
                int textColor = mBarrageBean.getColor();
                showBarrage(content, textSize, textColor);
            }
        }
    };

    private Set existMarginValues = new HashSet<>();
    private int linesCount;
    private int validHeightSpace;

    private int getRandomTopMargin() {
        //计算用于弹幕显示的空间高度
        if (validHeightSpace == 0) {
            validHeightSpace = mBarrageContainer.getBottom() - mBarrageContainer.getTop()
                    - mBarrageContainer.getPaddingTop() - mBarrageContainer.getPaddingBottom();
        }

        //计算可用的行数
        if (linesCount == 0) {
            linesCount = validHeightSpace / ScreenUtils.dip2px(this, mBarrageBean.getMinTextSize() * (1 + mBarrageBean.getRange()));
            if (linesCount == 0) {
                throw new RuntimeException("Not enough space to show text.");
            }
        }

        //检查重叠
        int checkTimes = 0;
        while (true) {
            int randomIndex = (int) (Math.random() * linesCount);
            int marginValue = randomIndex * (validHeightSpace / linesCount);

            if (!existMarginValues.contains(marginValue)) {
                existMarginValues.add(marginValue);
                return marginValue;
            }
            checkTimes++;
            if (checkTimes>=linesCount) {
                return marginValue;
            }
        }
    }
}
